home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / xinetd / xinetd.2.0.6 / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-22  |  4.5 KB  |  222 lines

  1. /*
  2.  * (c) Copyright 1992 by Panagiotis Tsirigotis
  3.  * All rights reserved.  The file named COPYRIGHT specifies the terms 
  4.  * and conditions for redistribution.
  5.  */
  6.  
  7. static char RCSid[] = "$Id: main.c,v 5.1 1992/11/01 00:01:21 panos Exp $" ;
  8. char program_version[] = VERSION ;
  9.  
  10. #include <sys/types.h>
  11. #include <sys/stat.h>
  12. #include <sys/time.h>
  13. #include <errno.h>
  14. #include <syslog.h>
  15.  
  16. #include "sio.h"
  17.  
  18. #include "service.h"
  19. #include "server.h"
  20. #include "state.h"
  21.  
  22.  
  23. struct program_state ps ;
  24. struct debug debug ;
  25.  
  26. extern int errno ;
  27.  
  28. void exit() ;
  29. void msg() ;
  30.  
  31. /*
  32.  * This is where the story starts...
  33.  */
  34. int main( argc, argv )
  35.     int argc ;
  36.     char *argv[] ;
  37. {
  38.     char *func = "main" ;
  39.     void init_services() ;
  40.     void main_loop() ;
  41.     void init_daemon() ;
  42.  
  43.     init_daemon( argc, argv ) ;
  44.     init_services() ;
  45.  
  46.     msg( LOG_NOTICE, func, "Started working: %d available service%s",
  47.         ps.rws.available_services,
  48.             ( ps.rws.available_services > 1 ) ? "s" : "" ) ;
  49.  
  50.     /*
  51.      * The reason for doing the setjmp here instead of in main_loop is
  52.      * that setjmp is not guaranteed to restore register values which
  53.      * can cause problem for register variables
  54.      */
  55.     if ( setjmp( ps.rws.env ) == 0 )
  56.         ps.rws.env_is_valid = TRUE ;
  57.  
  58.     main_loop() ;
  59.  
  60.     /* NOTREACHED */
  61. }
  62.  
  63.  
  64. /*
  65.  * What main_loop does:
  66.  *
  67.  *        check for signals
  68.  *        select on all active services
  69.  *        for each socket where a request is pending
  70.  *            try to start a server
  71.  */
  72. PRIVATE void main_loop()
  73. {
  74.     char *func = "main_loop" ;
  75.     void find_bad_fd() ;
  76.     void signal_wait() ;
  77.  
  78.     for ( ;; )
  79.     {
  80.         fd_set read_mask ;
  81.         register int n_active ;
  82.         register unsigned u ;
  83.  
  84.         if ( debug.on )
  85.             msg( LOG_DEBUG, func,
  86.                     "active_services = %d", ps.rws.active_services ) ;
  87.  
  88.         /*
  89.          * Check flags returns true if any of the flags is set AND
  90.          * the loop must be restarted
  91.          */
  92.         if ( check_flags() )
  93.             continue ;
  94.  
  95.         if ( ps.rws.active_services == 0 )
  96.         {
  97.             signal_wait() ;
  98.             continue ;
  99.         }
  100.  
  101.         read_mask = ps.rws.socket_mask ;
  102.         n_active = select( ps.rws.mask_max+1, &read_mask,
  103.                                 FD_SET_NULL, FD_SET_NULL, TIMEVAL_NULL ) ;
  104.         if ( n_active == -1 )
  105.         {
  106.             if ( errno == EINTR )
  107.                 continue ;
  108.             else if ( errno == EBADF )
  109.                 find_bad_fd() ;
  110.             else
  111.                 msg( LOG_NOTICE, func, "select error: %m" ) ;
  112.             continue ;
  113.         }
  114.         else if ( n_active == 0 )
  115.             continue ;
  116.  
  117.         if ( debug.on )
  118.             msg( LOG_DEBUG, func, "select returned %d", n_active ) ;
  119.  
  120.         for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
  121.         {
  122.             register struct service *sp ;
  123.  
  124.             sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
  125.  
  126.             if ( ! IS_ACTIVE( sp ) )
  127.                 continue ;
  128.  
  129.             if ( FD_ISSET( SVC_FD( sp ), &read_mask ) )
  130.             {
  131.                 svc_request( sp ) ;
  132.                 if ( --n_active == 0 )
  133.                     break ;
  134.             }
  135.         }
  136.         if ( n_active > 0 )
  137.             msg( LOG_ERR, func, "%d descriptors still set", n_active ) ;
  138.     }
  139. }
  140.  
  141.  
  142.  
  143. /*
  144.  * This function identifies if any of the fd's in the socket mask
  145.  * is bad. We use it in case select(2) returns EBADF
  146.  * When we identify such a bad fd, we remove it from the mask
  147.  * and deactivate the service.
  148.  */
  149. PRIVATE void find_bad_fd()
  150. {
  151.     register int fd ;
  152.     struct stat st ;
  153.     unsigned bad_fd_count = 0 ;
  154.     char *func = "find_bad_fd" ;
  155.  
  156.     for ( fd = 0 ; fd < ps.ros.max_descriptors ; fd++ )
  157.         if ( FD_ISSET( fd, &ps.rws.socket_mask ) && fstat( fd, &st ) == -1 )
  158.         {
  159.             int found = FALSE ;
  160.             register unsigned u ;
  161.  
  162.             for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
  163.             {
  164.                 register struct service *sp ;
  165.  
  166.                 sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
  167.  
  168.                 if ( ! IS_AVAILABLE( sp ) )
  169.                     continue ;
  170.  
  171.                 if ( SVC_FD( sp ) == fd )
  172.                 {
  173.                     msg( LOG_ERR, func,
  174.                         "file descriptor of service %s has been closed",
  175.                                         CONF( sp )->id ) ;
  176.                     svc_deactivate( sp ) ;
  177.                     found = TRUE ;
  178.                     break ;
  179.                 }
  180.             }
  181.             if ( ! found )
  182.             {
  183.                 FD_CLR( fd, &ps.rws.socket_mask ) ;
  184.                 msg( LOG_ERR, func,
  185.                     "No active service for file descriptor %d\n", fd ) ;
  186.                 bad_fd_count++ ;
  187.             }
  188.         }
  189.     if ( bad_fd_count == 0 )
  190.         msg( LOG_NOTICE, func,
  191.             "select reported EBADF but no bad file descriptors were found" ) ;
  192. }
  193.  
  194.  
  195. /*
  196.  * Deactivates all active processes.
  197.  * The real reason for doing this instead of just exiting is
  198.  * to deregister the RPC services
  199.  */
  200. void quit_program()
  201. {
  202.     register unsigned u ;
  203.     char *func = "quit_program" ;
  204.  
  205.     for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
  206.         svc_deactivate( SP( pset_pointer( SERVICES( ps ), u ) ) ) ;
  207.     msg( LOG_WARNING, func, "Exiting..." ) ;
  208.     exit( 0 ) ;
  209. }
  210.  
  211.  
  212. void terminate_program()
  213. {
  214.     register unsigned u ;
  215.     void terminate_servers() ;
  216.  
  217.     for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
  218.         terminate_servers( SP( pset_pointer( SERVICES( ps ), u ) ) ) ;
  219.     quit_program() ;
  220. }
  221.  
  222.